package rise.net;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.ServerSocket;
import java.net.Socket;

import org.w3c.dom.Document;

import rise.comunity.Status;
import rise.comunity.User;
import rise.comunity.UserData;
import rise.message.Packet;
import rise.message.PacketType;
import rise.net.handler.CommunityStatusNotificationHandler;
import rise.net.handler.MessageHandler;
import rise.net.handler.StatusNotificationHandler;
import rise.ui.Conversation;
import rise.ui.R;
import rise.ui.UserListActivity;
import android.app.Notification;
import android.app.NotificationManager;
import android.app.PendingIntent;
import android.app.Service;
import android.content.Intent;
import android.os.ConditionVariable;
import android.os.IBinder;
import android.util.Log;

public class ReceiverService extends Service {

	private boolean running;
	public final ConditionVariable conditionalVariable = new ConditionVariable(
			true);
	public static final int NEW_MESSAGE = 0;
	public static final int STATUS_NOTIFICATION = 1;

	@Override
	public IBinder onBind(Intent intent) {
		return null;
	}

	@Override
	public void onCreate() {
		super.onCreate();

		ReceiverService.receiverService = this;
		this.startService();
	}

	public void stopService() {
		this.running = false;
	}

	public void startService() {
		ReceiverService.this.conditionalVariable.close();
		this.running = true;

		new Thread(new Receiver()).start();
	}

	private void notifyNewMessage(String username) {
		Intent intent = new Intent(this, Conversation.class);
		intent.putExtra("username", username);
		PendingIntent contentIntent = PendingIntent.getActivity(this, 0,
				intent, 0);

		NotificationManager notificationManager = (NotificationManager) getSystemService(NOTIFICATION_SERVICE);
		Notification notif = new Notification.Builder(this)
				.setContentTitle("Nuovo messaggio.")
				.setContentText(username + " ti ha inviato un nuovo messaggio.")
				.setTicker(username + " ti ha inviato un nuovo messaggio.")
				.setSmallIcon(R.drawable.arrow).setContentIntent(contentIntent)
				.setAutoCancel(true).build();

		notificationManager.notify(username, NEW_MESSAGE, notif);
	}

	private void notifyStatusUpdate(String username, Status status) {
		PendingIntent contentIntent = PendingIntent.getActivity(this, 0,
				new Intent(this, UserListActivity.class), 0);

		int drawableStatus = R.drawable.online;
		if (status == Status.OFFLINE) {
			drawableStatus = R.drawable.invisible;
		} else if (status == Status.BUSY) {
			drawableStatus = R.drawable.busy;
		}
		NotificationManager notificationManager = (NotificationManager) getSystemService(NOTIFICATION_SERVICE);
		Notification notif = new Notification.Builder(this)
				.setContentTitle("Aggiornamento di stato")
				.setContentText(username + " ha cambiato il proprio stato.")
				.setTicker(username + " ha cambiato il proprio stato.")
				.setSmallIcon(drawableStatus).setContentIntent(contentIntent)
				.setAutoCancel(true).build();

		notificationManager.notify(STATUS_NOTIFICATION, notif);
	}

	class Receiver implements Runnable {

		@Override
		public void run() {
			while (ReceiverService.this.running) {
				try {
					this._run();
				} catch (IOException e) {
					Log.e("-","Eccezione nel servizio");
					ReceiverService.this.running = false;
				}
			}
			ReceiverService.this.conditionalVariable.open();
		}

		private void _run() throws IOException {
			if(UserData.obtainUserData() == null){
				ReceiverService.this.running = false;
				return;
			}
			BufferedReader in = UserData.obtainUserData().getBufferedReader();

			String packetRappresentation = in.readLine();
			
			if(packetRappresentation == null)
				return;
			while (packetRappresentation.charAt(0) != '<'){
				packetRappresentation = packetRappresentation.substring(1);
			}
			Log.e("-","[in] "+packetRappresentation);
			this.immediateHandling(packetRappresentation);
		}

		private int immediateHandling(String packetRappresentation) {
			Document doc = Packet
					.createXMLDocumentFromString(packetRappresentation);
			String rootTag = doc.getChildNodes().item(0).getNodeName();

			if (rootTag.equals(PacketType.MESSAGE.toString())) {
				MessageHandler messageHandler = new MessageHandler(
						packetRappresentation);
				ReceiverService.this.notifyNewMessage(messageHandler
						.getSender());
				new Thread(messageHandler).start();
				return Packet.OK;
			}
			if (rootTag.equals(PacketType.STATUS_NOTIFICATION.toString())) {
				StatusNotificationHandler statusNotificationHandler = new StatusNotificationHandler(
						packetRappresentation);
				ReceiverService.this.notifyStatusUpdate(
						statusNotificationHandler.getSender(),
						statusNotificationHandler.getSenderStatus());
				new Thread(statusNotificationHandler).start();
				return Packet.OK;
			}
			if (rootTag.equals(PacketType.COMMUNITY_STATUS_NOTIFICATION
					.toString())) {
				new Thread(new CommunityStatusNotificationHandler(
						packetRappresentation)).start();
				return Packet.OK;
			}
			return Packet.UNKNOWN_PACKET;
		}

		@Override
		protected void finalize() throws Throwable {
			/*UserData userData = UserData.obtainUserData();
			if (userData.existSocket())
				userData.closeSocket();*/
		}
	}

	private static ReceiverService receiverService;

	public synchronized static ReceiverService obtainReceiverService() {
		return receiverService;
	}

	public synchronized boolean isRunning() {
		return receiverService.running;
	}
}
